面向过程与面向对象_文本查询程序

之前总是习惯编写面向过程的程序,没有面向对象的思维,用这个文本查询程序作为一个面向对象的小练习.
用面向过程的方式很快就写完了,用面向对象实现的时候还是遇到不少小问题.
这个小程序实现了”打印文本中存在某单词所在的行”的功能:

1
2
3
4
5
root@yifei: ./textquery data.txt hello
查询到3个hello.
(line 2) ni hao a hello
(line 33) hello daming
(line 40 hello world.

面向过程实现文本查询程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <string>
#include <list>
#include <forward_list>
#include <deque>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <numeric>
#include <ctime>
#include <iterator>
#include <utility>
#include <memory>

using namespace std;

//判断文件名是否满足要求.
bool judgefilename(string filename){
string tail=".txt";
if(filename.compare(filename.size()-tail.size(),tail.size(),tail)==0){
return false;
}else{
cout<<"sorry,我只接受txt文件."<<endl;
return true;
}
}

//判断该行中是否含有要查询的文本
bool hasTextFromLine(string line,string querytext){
if(line.find(querytext,0)!=string::npos){
return true;
}else{
return false;
}
}

//打印查询结果
void printResult(map<int,string> &result,string querytext){
if(result.size()==0){
cout<<"查询到0个"<<querytext<<"."<<endl;
return ;
}
cout<<"查询到"<<result.size()<<"个"<<querytext<<endl;
for(auto a:result){
cout<<" (line ";
cout<<a.first<<") "<<a.second<<endl;
}
}

int main(int argc,char *argv[]){
/*
面向过程方法:
1.根据参数打开文件
2.读入文本并建立行号-那一行内容的map
3.查询含有结果的pair保存到map2中
4.输出map2的内容
*/
//变量定义
map<int,string> misfile;
map<int,string> misresult;

//输入参数判断
if(argc!=3){
cout<<"格式: <textquery> <filename> <text> ,请重新输入!"<<endl;
return -1;
}
string filename(argv[1]);
string text(argv[2]);
if(text.size()>100||judgefilename(filename)){
cout<<"参数错误! 请重新输入."<<endl;
return -2;
}

//读入文件 & 得出查询结果
ifstream is1(filename);
string tmp;
int linefile=1,lineresult=1;
while(getline(is1,tmp)){
misfile.insert({linefile,tmp}); linefile++;
if(hasTextFromLine(tmp,text)){
misresult.insert({lineresult,tmp});
lineresult++;
}
}

//输出查询结果
printResult(misresult,text);

return 0;
}

面向对象实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//textquery.cpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <string>
#include <list>
#include <forward_list>
#include <deque>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <numeric>
#include <ctime>
#include <iterator>
#include <utility>
#include <memory>
#include "TransactionProcess.h"
#include "QueryResult.h"//此头文件要在TextQuery.h前面
#include "TextQuery.h"

using namespace std;

/*
面向对象:
TransactionProcess:
私有成员:
int argc;
char *argv[];
成员函数:
判断参数;

TextQuery:
private:
存储整个文件的map<int,string>
QueryResult与TextQuery可以共享同一个map,所以使用shared_ptr

public:
空构造函数
使用文件名初始化

返回文件map的shared_ptr
读入string,查询之后返回vector<int>

QueryResult:
private:
string querytext 要查询的单词
shared_ptr<map<int,string>> misres_ptr 所有行的内容
vector<int> vires; 只标记拥有所查询单词的行号

public:
空构造函数
构造函数

打印结果的友元函数
*/

int main(int argc,char *argv[]){
TransactionProcess tranpro1(argc,argv);
if(tranpro1.judgeArg()==false) return -1;

shared_ptr<map<int,string>> smis=make_shared<map<int,string>>();
TextQuery tq(string(argv[1]),smis);
tq.textInput();
vector<int> vitmp=tq.returnResult(argv[2]);
QueryResult qr(argv[2],tq.returnFile(),vitmp);

printResult(qr);

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//TransactionProcess.h
#ifndef TRAN_PROC
#define TRAN_PROC
#include <iostream>
using namespace std;

class TransactionProcess{
private:
int argc;
char *argv[5];
public:
TransactionProcess()=default;

//TransactionProcess(int argc1,char *argv1[]):argc(argc1),argv(argv1) {}
TransactionProcess(int argc1,char *argv1[]);
bool judgeArg();
bool judgefilename(string filename);
};

TransactionProcess::TransactionProcess(int argc1,char *argv1[]){
argc=argc1;
for(int i=0;i<argc1;i++){
argv[i]=argv1[i];
}
}

bool TransactionProcess::judgeArg(){
//输入参数判断
if(argc!=3){
cout<<"格式: <textquery> <filename> <text> ,请重新输入!"<<endl;
return false;
}
string filename(argv[1]);
string text(argv[2]);
if(text.size()>100||judgefilename(filename)){
cout<<"参数错误! 请重新输入."<<endl;
return false;
}
return true;
}

//判断文件名是否满足要求.
bool TransactionProcess::judgefilename(string filename){
string tail=".txt";
if(filename.compare(filename.size()-tail.size(),tail.size(),tail)==0){
return false;
}else{
cout<<"sorry,我只接受txt文件."<<endl;
return true;
}
}

#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//TextQuery.h
#ifndef TEXTQUERY
#define TEXTQUERY
#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <map>
#include <fstream>

using namespace std;

class QueryResult;

class TextQuery{
private:
shared_ptr<map<int,string>> mis_ptr;
string textq;
public:
TextQuery()=default;
TextQuery(string str,shared_ptr<map<int,string>> ptr) : textq(str), mis_ptr(ptr) {}

void textInput();
shared_ptr<map<int,string>> returnFile();
vector<int> returnResult(string querytxt);
};

void TextQuery::textInput(){
ifstream fnameis(textq);
//读入文件
string tmp;
int linefile=1;
while(getline(fnameis,tmp)){
mis_ptr->insert({linefile,tmp}); linefile++;
}

}

shared_ptr<map<int,string>> TextQuery::returnFile(){
return mis_ptr;
}

vector<int> TextQuery::returnResult(string querytxt){
vector<int> vi1;
for(auto a:*mis_ptr){
if(a.second.find(querytxt)!=string::npos){
vi1.push_back(a.first);
}
}
return vi1;
}

#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//QueryResult.h
#ifndef QUERYRESULT
#define QUERYRESULT
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <map>
using namespace std;

class QueryResult{
private:
string querytext;
shared_ptr<map<int,string>> misres_ptr;
vector<int> vires;
public:
QueryResult()=default;
QueryResult(string qt,shared_ptr<map<int,string>> misptr,vector<int> vi) :
querytext(qt),misres_ptr(misptr),vires(vi) {}
public:
friend void printResult(QueryResult &qr1);
};
//QueryResult::QueryResult(string qt,shared_ptr<map<int,string>> misptr,vector<int> vi){
//}

//打印查询结果
void printResult(QueryResult &qr1){
if(qr1.vires.size()==0){
cout<<"查询到0个"<<qr1.querytext<<"."<<endl;
return ;
}
cout<<"查询到"<<qr1.vires.size()<<"个"<<qr1.querytext<<endl;
for(auto a:qr1.vires){
cout<<" (line ";
cout<<a<<") "<<(*qr1.misres_ptr)[a]<<endl;
}
}
#endif

总结

  • 头文件包含顺序
    当ClassA.h中需要创建ClassB.h中的类的时候,如果a.cpp中需要包含以上两个头文件,那么在a.cpp中需要首先引用ClassB.h,然后再引用ClassA.h.
  • 友元函数
    1.友元函数可以访问类中的私有成员和其他数据,但是访问不可直接使用数据成员,需要通过对对象进行引用。
    2.友元函数在调用上同一般函数一样,不必通过对对象进行引用。
    3.一个类中的成员函数可以是另外一个类的友元函数,而且一个函数可以是多个类的友元函数。
    4.类中通过使用关键字friend 来修饰友元函数,但该函数并不是类的成员函数,其声明可以放在类的私有部分,也可放在共有部分。友元函数的定义在类体外实现,不需要加类限定。
  • 当不同的类可以共用数据时,可以利用shared_ptr智能指针来共享数据.
  • 查找一个string中是否包含另一个string
    1
    2
    3
    4
    5
    if(stra.find(strb)!=string::npos){//该函数返回该串的位置
    cout<<"存在该串"<<endl;
    }else{
    cout<<"不存在"<<endl;
    }

欢迎与我分享你的看法。
转载请注明出处:http://taowusheng.cn/